#ifndef __MATH_PARSER_H__
  #define __MATH_PARSER_H__

#include <string>
#include <sstream>
#include <cmath>
#include <cstring>

using namespace std;

//! Parser for mathematical operations

/*!
This class parses mathematical operations.

Implementation date: 2006

Usage:

\code
string str_tmp;
cout << math_parser::parse("2+2", str_tmp) << endl;
cout << math_parser::parse("2^10", str_tmp, true) << endl; // 1,024 (using thousand-separator)
cout << math_parser::parse("2^100", str_tmp, true) << endl; // 1.2676506002e+30
cout << math_parser::parse("sin(abs(-30))", str_tmp, true) << endl; // 0.5
cout << math_parser::parse("solve{70:100;20:x}", str_tmp, true) << endl; // 28.571428571
\endcode
*/

class math_parser {
private:
  math_parser &operator=(const math_parser &mp); // not allowed
  math_parser(const math_parser &mp); // not allowed

  static string par_parse(const string &s, size_t &begin, size_t &end);
  static void fun_parse(string &s); // parses functions like sin, cos, ...
  static void fac_parse(string &s); // parses factoriel
  static void pow_parse(string &s); // parses power
  static void mul_parse(string &s); // parses multiplications & divisions
  static void plu_parse(string &s); // parses additions & subtractions

public:
  //! checks the given string to see if all open parenthesis are closed correctly (may throw an exception)
  static void check_parenthesis(const string &s);

  //! checks the given string to see if there is any mistake in it (may throw an exception)
  static void check_mistakes(const string &s);

  //! parses the given string. the output can be formated using the thousand separator
  /*!
  supported operations are:
  \li +
  \li -
  \li *
  \li /
  \li %
  \li ^
  \li !

  supported functions are:
  \li log
  \li ln
  \li sin
  \li cos
  \li tan
  \li int
  \li abs
  \li sgn
  \li sqr
  \li fac
  \li b2d
  \li h2d
  \li solve{a,b;c,x}

  supported constants are:
  \li PI
  \li E
  */
  static string &parse(const string &s, string &output, bool separator = false);
};

#endif
